package com.xsf.pay.common.utils;

import cn.hutool.core.collection.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author
 */
public class StringUtils {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private static Pattern CHINESE_PHONE_PATTERN = Pattern.compile("^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$");

    /**
     * 检查指定的字符串列表是否不为空。
     */
    public static boolean areNotBlank(String... values) {
        boolean result = true;
        if (values == null || values.length == 0) {
            result = false;
        } else {
            for (String value : values) {
                result &= !isBlank(value);
            }
        }
        return result;
    }

    public static boolean isValidPhone(String phone) {
        if (phone == null || phone.length() != 11) {
            return false;
        }
        Matcher matcher = CHINESE_PHONE_PATTERN.matcher(phone);
        return matcher.matches();

    }

    /**
     * 字符串省略
     *
     * @param params
     * @return
     */
    public static String paramLog(String params, boolean isproduction, int num) {
        StringBuffer buf = new StringBuffer();
        if (params.length() > num && isproduction) {
            buf.append(params.substring(0, num)).append("...");
        } else {
            buf.append(params);
        }
        return buf.toString();
    }

    /**
     * 获取IP
     *
     * @param request
     * @return
     * @throws Exception
     */
    public static String getIpAddr(HttpServletRequest request) throws Exception {
        String ip = request.getHeader("X-FORWARDED-FOR");
        String unKnown = "unknown";
        String comma = ",";
        int length = 2;
        if (ip != null && ip.length() > 0 && !unKnown.equalsIgnoreCase(ip)) {
            if (ip.contains(comma) && ip.split(comma).length >= length) {
                String[] ipStr = ip.split(comma);
                return ipStr[ipStr.length - 1];
            } else {
                return ip;
            }
        }
        if (ip == null || ip.length() == 0 || unKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || unKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || unKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || unKnown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || unKnown.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.contains(comma)) {
            return ip.split(comma)[0];
        } else {
            return ip;
        }
    }

    public static String createRandomNum(int num) {
        StringBuilder randomNumStr = new StringBuilder();
        for (int i = 0; i < num; i++) {
            int randomNum = (int) (Math.random() * 10);
            randomNumStr.append(randomNum);
        }
        return randomNumStr.toString();
    }

    /**
     * 产生紧凑型32位UUID
     *
     * @return
     */
    public static String getUuid() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replaceAll("-", "");
    }

    /**
     * 遮蔽银行卡号
     *
     * @param cardNo 银行卡号
     * @return
     * @author Joakim
     * @date 2014-12-2
     * @version 1.0.0
     */
    public static String hideCardNo(String cardNo) {
        int len = cardNo.length();
        int leng = 10;
        if (len < leng) {
            return cardNo;
        }
        return cardNo.substring(0, 6) + cardNo.substring(6, len - 4).replaceAll("\\d", "*") + cardNo.substring(len - 4);
    }

    /**
     * 遮蔽身份证号
     *
     * @param cardId 身份证号
     * @return
     * @author Joakim
     * @date 2014-12-3
     * @version 1.0.0
     */
    public static String hideCardId(String cardId) {
        int len = cardId.length();
        int len18 = 18;
        int len15 = 15;

        if (len == len18) {
            return cardId.substring(0, 6) + cardId.substring(3, len - 6).replaceAll("\\d", "*") + cardId.substring(len - 4, len);
        } else if (len == len15) {
            return cardId.substring(0, 3) + cardId.substring(3, len - 5).replaceAll("\\d", "*") + cardId.substring(len - 5, len - 1) + "*";
        } else {
            return cardId;
        }
    }

    /**
     * 隐蔽手机号
     *
     * @param phoneNo 手机号
     * @return
     * @author Joakim
     * @date 2014-12-3
     * @version 1.0.0
     */
    public static String hidePhone(String phoneNo) {
        int len = phoneNo.length();
        return phoneNo.substring(0, 3) + phoneNo.substring(3, len - 4).replaceAll("\\d", "*") + phoneNo.substring(len - 4);
    }


    public static String hideLicenseNo(String licenseNo) {
        int leng7 = 7;
        if (null != licenseNo) {
            if (licenseNo.length() > leng7) {
                String replaceVal = licenseNo.substring(0, 3) + licenseNo.substring(4, licenseNo.length() - 4).replaceAll("[\\D\\d]", "*") + licenseNo.substring(licenseNo.length() - 4);
                return replaceVal;
            }
            return hidePhone(licenseNo);
        }
        return licenseNo;
    }


    /**
     * 字符串左边补零
     * <p>
     * <p>
     * <p>
     * <p>
     * 例：将字符串"ABC"用"0"补足8位，结果为"00000ABC"
     *
     * @param orgStr   原始字符串
     * @param fillWith 用来填充的字符
     * @param fixLen   固定长度
     * @return
     */
    public static String fillLeft(String orgStr, char fillWith, int fixLen) {
        return fillStr(orgStr, fillWith, fixLen, true);
    }

    /**
     * 字符串右边补零
     *
     * @param orgStr
     * @param fillWith
     * @param fixLen
     * @return
     */
    public static String fillRight(String orgStr, char fillWith, int fixLen) {

        return fillStr(orgStr, fillWith, fixLen, false);

    }

    private static String fillStr(String orgStr, char fillWith, int fixLen,
                                  boolean isLeft) {

        int toFill = fixLen - orgStr.length();

        if (toFill <= 0) {
            return orgStr;
        }

        StringBuilder sb = new StringBuilder(orgStr);
        for (; toFill > 0; toFill--) {
            if (isLeft) {
                sb.insert(0, fillWith);
            } else {
                sb.append(fillWith);
            }

        }

        return sb.toString();

    }

    /**
     * 获取异常的堆栈信息
     *
     * @param t
     * @return
     */
    public static String getStackTrace(Throwable t) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        try {
            t.printStackTrace(pw);
            return sw.toString();
        } finally {
            pw.close();
        }
    }


    private static byte toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * <p>Deletes all whitespaces from a String as defined by
     * {@link Character#isWhitespace(char)}.</p>
     *
     * <pre>
     * StringUtils.deleteWhitespace(null)         = null
     * StringUtils.deleteWhitespace("")           = ""
     * StringUtils.deleteWhitespace("abc")        = "abc"
     * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
     * </pre>
     *
     * @param str the String to delete whitespace from, may be null
     * @return the String without whitespaces, <code>null</code> if null String input
     */
    public static String deleteWhitespace(String str) {
        if (isEmpty(str)) {
            return str;
        }
        int sz = str.length();
        char[] chs = new char[sz];
        int count = 0;
        for (int i = 0; i < sz; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                chs[count++] = str.charAt(i);
            }
        }
        if (count == sz) {
            return str;
        }
        return new String(chs, 0, count);
    }

    public static boolean isEmpty(final CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    /**
     * 货币转换
     * "分"转换为"元" (单位)
     * 100分->￥1.00
     * 00000分->0.00
     *
     * @param decimal
     * @return
     */
    public static String converBigDecimalDivide(String decimal) {
        if (decimal != null) {
            try {
                BigDecimal bigDecimal = new BigDecimal(decimal);
                if (bigDecimal.compareTo(new BigDecimal(0)) == 0) {
                    return "0.00";
                }
                BigDecimal bigDecimal1 = new BigDecimal(100);
                BigDecimal deciaml = bigDecimal.divide(bigDecimal1).setScale(2, BigDecimal.ROUND_DOWN);
                return deciaml.toString();
            } catch (Exception e) {
                return "";
            }
        }
        return "";
    }


    /**
     * 前六后四显示银行卡号
     *
     * @param bankCard
     * @return
     */
    public static String bankCardNoMask(String bankCard) {
        if (isEmpty(bankCard)) {
            return bankCard;
        }
        StringBuilder retS = new StringBuilder();
        for (int i = 0; i < bankCard.length(); i++) {
            if (i <= 5 || i >= bankCard.length() - 4) {
                retS.append(bankCard.charAt(i));
            } else {
                retS.append("*");
            }
        }
        return retS.toString();
    }


    /**
     * 按指定大小，分隔集合，将集合按规定个数分为n个部分
     *
     * @param list
     * @param len
     * @return
     */
    public static <T> List<List<T>> splitList(List<T> list, int len) {
        if (list == null || list.size() == 0 || len < 1) {
            return null;
        }

        List<List<T>> result = new ArrayList<List<T>>();

        int size = list.size();
        int count = (size + len - 1) / len;

        for (int i = 0; i < count; i++) {
            List<T> subList = list.subList(i * len, ((i + 1) * len > size ? size : len * (i + 1)));
            result.add(subList);
        }
        return result;
    }

    /**
     * 将百分百费率转换为6位整数<br>
     * 例如：0.38% --> 003800<br>
     * 空的情况下返回00000<br>
     *
     * @param rate
     * @return
     */
    public static String convertRateToString(String rate) {
        if (isBlank(rate)) {
            return "000000";
        }
        BigDecimal bd1 = new BigDecimal(rate);
        BigDecimal bd2 = new BigDecimal(10000);
        String tmpStr = bd1.multiply(bd2).setScale(0, BigDecimal.ROUND_HALF_UP).toString();
        return fillLeft(tmpStr, '0', 6);
    }

    public static boolean isBlank(final CharSequence cs) {
        final int strLen = length(cs);
        if (strLen == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(cs.charAt(i))) {
                return false;
            }
        }
        return true;
    }


    public static int length(final CharSequence cs) {
        return cs == null ? 0 : cs.length();
    }

    /**
     * 获取当前时间
     *
     * @param pattern 时间格式化
     * @return
     */
    public static String getNowDate(String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(Calendar.getInstance().getTime());
    }

    /**
     * 校验地址
     *
     * @param checkRequestUrl
     * @param urls
     * @return
     */
    public static boolean checkUrl(String checkRequestUrl, String urls, String contextPath) {
        boolean flag = false;
        if (StringUtils.isBlank(urls)) {
            return flag;
        }
        List<String> list = new ArrayList<>();
        String[] urlsArr = urls.split(",");
        for (String url : urlsArr) {
            list.add((contextPath + url).replaceAll(" ", ""));
        }
        for (String url : list) {
            if (StringUtils.match(url, checkRequestUrl)) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    /**
     * 校验地址
     *
     * @param checkRequestUrl
     * @param urls
     * @return
     */
    public static boolean checkUrl(String checkRequestUrl, List<String> urls, String contextPath) {
        boolean flag = false;
        if (CollectionUtil.isEmpty(urls)) {
            return flag;
        }
        List<String> list = new ArrayList<>();
        for (String url : urls) {
            list.add((contextPath + url).replaceAll(" ", ""));
        }
        for (String url : list) {
            if (StringUtils.match(url, checkRequestUrl)) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    /**
     * 匹配资料
     *
     * @param patternPath 模糊匹配表达式
     * @param requestPath 待匹配的url
     * @return
     */
    public static boolean match(String patternPath, String requestPath) {
        if (StringUtils.isEmpty(patternPath) || StringUtils.isEmpty(requestPath)) {
            return false;
        }
        PathMatcher matcher = new AntPathMatcher();
        return matcher.match(patternPath, requestPath);
    }

    /**
     * 随机数
     *
     * @param length
     * @return
     */
    public static String createRandomCharData(int length) {
        StringBuilder sb = new StringBuilder();
        Random rand = new Random();
        Random randdata = new Random();
        int data = 0;
        for (int i = 0; i < length; i++) {
            int index = rand.nextInt(3);
            //目的是随机选择生成数字，大小写字母
            switch (index) {
                case 0:
                    data = randdata.nextInt(10);
                    sb.append(data);
                    break;
                case 1:
                    data = randdata.nextInt(26) + 65;
                    sb.append((char) data);
                    break;
                case 2:
                    data = randdata.nextInt(26) + 97;
                    sb.append((char) data);
                    break;
                default:
                    data = randdata.nextInt(26) + 65;
                    sb.append((char) data);
                    break;
            }
        }
        return sb.toString();
    }

    public static String getRandomCharAndNumr(Integer length) {
        String str = "";
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            boolean b = random.nextBoolean();
            if (b) { // 字符串
                // int choice = random.nextBoolean() ? 65 : 97; 取得65大写字母还是97小写字母
                str += (char) (97 + random.nextInt(26));// 取得大写字母
            } else { // 数字
                str += String.valueOf(random.nextInt(10));
            }
        }
        return str;
    }

    /**
     * 判断是否有特殊字符
     *
     * @param str
     * @return
     */
    public static boolean isSpecialChar(String str) {
        String regEx = "[ _`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。，、？]|\n|\r|\t";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.find();
    }

    /**
     * 判断是否为数字
     *
     * @param str
     * @return
     */
    public static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]*");
        return pattern.matcher(str).matches();
    }

    /**
     * 费率转化
     *
     * @param amont
     * @return
     */
    public static String convertStringToRate(String amont) {
        if (isBlank(amont)) {
            return "";
        }
        String zero5 = "00000";
        String zero6 = "000000";
        if (zero5.equals(amont) || zero6.equals(amont)) {
            return "0";
        }
        BigDecimal bigDecimal = new BigDecimal(amont);
        BigDecimal divide = bigDecimal.divide(new BigDecimal(10000));
        return divide.toString();
    }

    public static String yuanToFen(String yuan) {
        final String defaultNull = "-";
        if (isBlank(yuan) || defaultNull.equals(yuan)) {
            return "0";
        }
        BigDecimal yan = new BigDecimal(yuan);
        BigDecimal to = new BigDecimal(100);
        BigDecimal fens = yan.multiply(to);

        return fens.toString().split("\\.")[0];
    }

    /**
     * 分转元
     *
     * @param yuan
     * @return
     */
    public static String fenToYuan(String yuan) {
        if (isBlank(yuan)) {
            return "0.00";
        }
        BigDecimal yan = new BigDecimal(yuan);
        BigDecimal to = new BigDecimal(100);
        BigDecimal yuanRmb = yan.divide(to, 2, BigDecimal.ROUND_HALF_UP);

        return yuanRmb.toString();
    }

    /**
     * 分转元
     *
     * @param yuan
     * @return
     */
    public static String negativeFenToYuan(String yuan) {
        if (isBlank(yuan)) {
            return "0.00";
        }
        BigDecimal yan = new BigDecimal(yuan);
        BigDecimal to = new BigDecimal(100);
        BigDecimal yuanRmb = yan.divide(to, 2, BigDecimal.ROUND_HALF_UP).negate();

        return yuanRmb.toString();
    }

    /**
     * 费率+百分号
     *
     * @param yuan
     * @return
     */
    public static String percent(String yuan) {
        if (isBlank(yuan)) {
            return "0%";
        }
        return yuan + "%";
    }

    /**
     * 空转0
     *
     * @param str 银行卡号
     * @return
     * @author Joakim
     * @date 2014-12-2
     * @version 1.0.0
     */
    public static String notNull(String str) {
        if (StringUtils.isBlank(str)) {
            return "0";
        }
        return str;
    }

    /**
     * 空转0
     *
     * @param str 银行卡号
     * @return
     * @author Joakim
     * @date 2014-12-2
     * @version 1.0.0
     */
    public static String notPercentSign(String str) {
        if (StringUtils.isBlank(str)) {
            return str;
        }
        return str.replace("%", "");
    }
}
